Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


nomadnet/examples/messageboard/messageboard.py ace2969770ebded4cea2d6d23d9823c3641f0965 (ace29697) Text, 6.74 KB

T8b949e# Simple message board that can be hosted on a NomadNet node, messages can be posted by 'conversing' with a unique peer, all messages are then forwarded to the message board.
T8b949e# https://github.com/chengtripp/lxmf_messageboard

Tff7b72import T7ee787RNS
Tff7b72import T7ee787LXMF
Tff7b72import T7ee787osTff7b72, T7ee787time
Tff7b72from T7ee787queue Tff7b72import Te6edf3Queue
Tff7b72import T7ee787RNST7ee787.T7ee787vendorT7ee787.T7ee787umsgpack Tff7b72as T7ee787msgpack

Te6edf3display_name Tff7b72= Ta5d6ff"Ta5d6ffNomadNet Message BoardTa5d6ff"
Te6edf3max_messages Tff7b72= T79c0ff20

Tff7b72def Td2a8ffsetup_lxmfTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3identitypathTb4b4b4)Tb4b4b4:
Te6edf3identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffrom_fileTb4b4b4(Te6edf3identitypathTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffLoaded identity from fileTa5d6ff'Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffNo Primary Identity file found, creating new...Ta5d6ff'Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Te6edf3identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Tb4b4b4)
Te6edf3identityTff7b72.Td2a8ffto_fileTb4b4b4(Te6edf3identitypathTb4b4b4)

Tff7b72return Te6edf3identity

Tff7b72def Td2a8fflxmf_deliveryTb4b4b4(Te6edf3messageTb4b4b4)Tb4b4b4:
T8b949e# Do something here with a received message
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffA message was received: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3messageTff7b72.Td2a8ffcontentTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff'Ta5d6ffutf-8Ta5d6ff'Tb4b4b4)Tb4b4b4)Tb4b4b4)

Te6edf3message_content Tff7b72= Te6edf3messageTff7b72.Td2a8ffcontentTff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff'Ta5d6ffutf-8Ta5d6ff'Tb4b4b4)
Te6edf3source_hash_text Tff7b72= Te6edf3RNSTff7b72.Td2a8ffhexrepTb4b4b4(Te6edf3messageTff7b72.Td2a8ffsource_hashTb4b4b4, Te6edf3delimitTff7b72=Tff7b72FalseTb4b4b4)

T8b949e#Create username (just first 5 char of your addr)
Te6edf3username Tff7b72= Te6edf3source_hash_textTb4b4b4[T79c0ff0Tb4b4b4:T79c0ff5Tb4b4b4]

Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffUsername: Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3usernameTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)

Te6edf3time_string Tff7b72= Te6edf3timeTff7b72.Td2a8ffstrftimeTb4b4b4(Ta5d6ff"Ta5d6ff%Ta5d6ffY-Ta5d6ff%Ta5d6ffm-Tffd700%dTa5d6ff Ta5d6ff%Ta5d6ffH:Ta5d6ff%Ta5d6ffM:Ta5d6ff%Ta5d6ffSTa5d6ff"Tb4b4b4, Te6edf3timeTff7b72.Td2a8fflocaltimeTb4b4b4(Te6edf3messageTff7b72.Td2a8fftimestampTb4b4b4)Tb4b4b4)
Te6edf3new_message Tff7b72= Ta5d6ff'Tffd700{}Ta5d6ff Tffd700{}Ta5d6ff: Tffd700{}Tffea00\nTa5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3time_stringTb4b4b4, Te6edf3usernameTb4b4b4, Te6edf3message_contentTb4b4b4)

T8b949e# Push message to board
T8b949e# First read message board (if it exists
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3boardpathTb4b4b4)Tb4b4b4:
Te6edf3f Tff7b72= Tffa657openTb4b4b4(Te6edf3boardpathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4)
Te6edf3message_board Tff7b72= Te6edf3msgpackTff7b72.Td2a8ffunpackTb4b4b4(Te6edf3fTb4b4b4)
Te6edf3fTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3message_board Tff7b72= Tb4b4b4[Tb4b4b4]

T8b949e#Check we aren't doubling up (this can sometimes happen if there is an error initially and it then gets fixed)
Tff7b72if Te6edf3new_message Tff7b72not Tff7b72in Te6edf3message_boardTb4b4b4:
T8b949e# Append our new message to the list
Te6edf3message_boardTff7b72.Td2a8ffappendTb4b4b4(Te6edf3new_messageTb4b4b4)

T8b949e# Prune the message board if needed
Tff7b72while Tffa657lenTb4b4b4(Te6edf3message_boardTb4b4b4) Tff7b72> Te6edf3max_messagesTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffPruning Message BoardTa5d6ff'Tb4b4b4)
Te6edf3message_boardTff7b72.Td2a8ffpopTb4b4b4(T79c0ff0Tb4b4b4)

T8b949e# Now open the board and write the updated list
Te6edf3f Tff7b72= Tffa657openTb4b4b4(Te6edf3boardpathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4)
Te6edf3msgpackTff7b72.Td2a8ffpackTb4b4b4(Te6edf3message_boardTb4b4b4, Te6edf3fTb4b4b4)
Te6edf3fTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)

T8b949e# Send reply
Te6edf3message_reply Tff7b72= Ta5d6ff'Tffd700{}Ta5d6ff_Tffd700{}Ta5d6ff_Your message has been added to the messageboardTa5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3source_hash_textTb4b4b4, Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3qTff7b72.Td2a8ffputTb4b4b4(Te6edf3message_replyTb4b4b4)

Tff7b72def Td2a8ffannounce_nowTb4b4b4(Te6edf3lxmf_destinationTb4b4b4)Tb4b4b4:
Te6edf3lxmf_destinationTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffsend_messageTb4b4b4(Te6edf3destination_hashTb4b4b4, Te6edf3message_contentTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
T8b949e# Make a binary destination hash from a hexadecimal string
Te6edf3destination_hash Tff7b72= Tffa657bytesTff7b72.Td2a8fffromhexTb4b4b4(Te6edf3destination_hashTb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffInvalid destination hashTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72return

T8b949e# Check that size is correct
Tff7b72if Tff7b72not Tffa657lenTb4b4b4(Te6edf3destination_hashTb4b4b4) Tff7b72== Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffTRUNCATED_HASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffInvalid destination hash lengthTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72elseTb4b4b4:
T8b949e# Length of address was correct, let's try to recall the
T8b949e# corresponding Identity
Te6edf3destination_identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffrecallTb4b4b4(Te6edf3destination_hashTb4b4b4)

Tff7b72if Te6edf3destination_identity Tff7b72== Tff7b72NoneTb4b4b4:
T8b949e# No path/identity known, we'll have to abort or request one
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffCould not recall an Identity for the requested address. You have probably never received an announce from it. Try requesting a path from the network first. In fact, letTa5d6ff'Ta5d6ffs do this now :)Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffrequest_pathTb4b4b4(Te6edf3destination_hashTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffOK, a path was requested. If the network knows a path, you will receive an announce with the Identity data shortly.Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)

Tff7b72elseTb4b4b4:
T8b949e# We know the identity for the destination hash, let's
T8b949e# reconstruct a destination object.
Te6edf3lxmf_destination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(Te6edf3destination_identityTb4b4b4, Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffOUTTb4b4b4, Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLETb4b4b4, Ta5d6ff"Ta5d6fflxmfTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdeliveryTa5d6ff"Tb4b4b4)

T8b949e# Create a new message object
Te6edf3lxm Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMessageTb4b4b4(Te6edf3lxmf_destinationTb4b4b4, Te6edf3local_lxmf_destinationTb4b4b4, Te6edf3message_contentTb4b4b4, Te6edf3titleTff7b72=Ta5d6ff"Ta5d6ffReplyTa5d6ff"Tb4b4b4, Te6edf3desired_methodTff7b72=Te6edf3LXMFTff7b72.Td2a8ffLXMessageTff7b72.Td2a8ffDIRECTTb4b4b4)

T8b949e# You can optionally tell LXMF to try to send the message
T8b949e# as a propagated message if a direct link fails
Te6edf3lxmTff7b72.Td2a8fftry_propagation_on_fail Tff7b72= Tff7b72True

T8b949e# Send it
Te6edf3message_routerTff7b72.Td2a8ffhandle_outboundTb4b4b4(Te6edf3lxmTb4b4b4)

Tff7b72def Td2a8ffannounce_checkTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3announcepathTb4b4b4)Tb4b4b4:
Te6edf3f Tff7b72= Tffa657openTb4b4b4(Te6edf3announcepathTb4b4b4, Ta5d6ff"Ta5d6ffrTa5d6ff"Tb4b4b4)
Te6edf3announce Tff7b72= Tffa657intTb4b4b4(Te6edf3fTff7b72.Td2a8ffreadlineTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6fffailed to open announcepathTa5d6ff'Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3announce Tff7b72= T79c0ff1

Tff7b72if Te6edf3announce Tff7b72> Tffa657intTb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffRecent announcementTa5d6ff'Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3f Tff7b72= Tffa657openTb4b4b4(Te6edf3announcepathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4)
Te6edf3next_announce Tff7b72= Tffa657intTb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72+ T79c0ff1800
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Tffa657strTb4b4b4(Te6edf3next_announceTb4b4b4)Tb4b4b4)
Te6edf3fTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Te6edf3announce_nowTb4b4b4(Te6edf3local_lxmf_destinationTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffAnnouncement sent, expr set 1800 secondsTa5d6ff'Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)

T8b949e#Setup Paths and Config Files
Te6edf3userdir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Ta5d6ff"Ta5d6ff~Ta5d6ff"Tb4b4b4)

Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Ta5d6ff"Ta5d6ff/etc/nomadmbTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Ta5d6ff"Ta5d6ff/etc/nomadmb/configTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3configdir Tff7b72= Ta5d6ff"Ta5d6ff/etc/nomadmbTa5d6ff"
Tff7b72elif Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3userdirTff7b72+Ta5d6ff"Ta5d6ff/.config/nomadmbTa5d6ff"Tb4b4b4) Tff7b72and Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3userdirTff7b72+Ta5d6ff"Ta5d6ff/.config/nomadmb/configTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3configdir Tff7b72= Te6edf3userdirTff7b72+Ta5d6ff"Ta5d6ff/.config/nomadmbTa5d6ff"
Tff7b72elseTb4b4b4:
Te6edf3configdir Tff7b72= Te6edf3userdirTff7b72+Ta5d6ff"Ta5d6ff/.nomadmbTa5d6ff"

Te6edf3storagepath Tff7b72= Te6edf3configdirTff7b72+Ta5d6ff"Ta5d6ff/storageTa5d6ff"
Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisdirTb4b4b4(Te6edf3storagepathTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3storagepathTb4b4b4)

Te6edf3identitypath Tff7b72= Te6edf3configdirTff7b72+Ta5d6ff"Ta5d6ff/storage/identityTa5d6ff"
Te6edf3announcepath Tff7b72= Te6edf3configdirTff7b72+Ta5d6ff"Ta5d6ff/storage/announceTa5d6ff"
Te6edf3boardpath Tff7b72= Te6edf3configdirTff7b72+Ta5d6ff"Ta5d6ff/storage/boardTa5d6ff"

T8b949e# Message Queue
Te6edf3q Tff7b72= Te6edf3QueueTb4b4b4(Te6edf3maxsize Tff7b72= T79c0ff5Tb4b4b4)

T8b949e# Start Reticulum and print out all the debug messages
Te6edf3reticulum Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTb4b4b4(Te6edf3loglevelTff7b72=Te6edf3RNSTff7b72.Td2a8ffLOG_VERBOSETb4b4b4)

T8b949e# Create a Identity.
Te6edf3current_identity Tff7b72= Te6edf3setup_lxmfTb4b4b4(Tb4b4b4)

T8b949e# Init the LXMF router
Te6edf3message_router Tff7b72= Te6edf3LXMFTff7b72.Td2a8ffLXMRouterTb4b4b4(Te6edf3identity Tff7b72= Te6edf3current_identityTb4b4b4, Te6edf3storagepath Tff7b72= Te6edf3configdirTb4b4b4)

T8b949e# Register a delivery destination (for yourself)
T8b949e# In this example we use the same Identity as we used
T8b949e# to instantiate the LXMF router. It could be a different one,
T8b949e# but it can also just be the same, depending on what you want.
Te6edf3local_lxmf_destination Tff7b72= Te6edf3message_routerTff7b72.Td2a8ffregister_delivery_identityTb4b4b4(Te6edf3current_identityTb4b4b4, Te6edf3display_nameTff7b72=Te6edf3display_nameTb4b4b4)

T8b949e# Set a callback for when a message is received
Te6edf3message_routerTff7b72.Td2a8ffregister_delivery_callbackTb4b4b4(Te6edf3lxmf_deliveryTb4b4b4)

T8b949e# Announce node properties

Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Ta5d6ffLXMF Router ready to receive on: Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Te6edf3local_lxmf_destinationTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Te6edf3announce_checkTb4b4b4(Tb4b4b4)

Tff7b72while Tff7b72TrueTb4b4b4:

T8b949e# Work through internal message queue
Tff7b72for Te6edf3i Tff7b72in Tffa657listTb4b4b4(Te6edf3qTff7b72.Td2a8ffqueueTb4b4b4)Tb4b4b4:
Te6edf3message_id Tff7b72= Te6edf3qTff7b72.Td2a8ffgetTb4b4b4(Tb4b4b4)
Te6edf3split_message Tff7b72= Te6edf3message_idTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff'Ta5d6ff_Ta5d6ff'Tb4b4b4)
Te6edf3destination_hash Tff7b72= Te6edf3split_messageTb4b4b4[T79c0ff0Tb4b4b4]
Te6edf3message Tff7b72= Te6edf3split_messageTb4b4b4[T79c0ff2Tb4b4b4]
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff'Tffd700{}Ta5d6ff Tffd700{}Ta5d6ff'Tff7b72.Td2a8ffformatTb4b4b4(Te6edf3destination_hashTb4b4b4, Te6edf3messageTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Te6edf3send_messageTb4b4b4(Te6edf3destination_hashTb4b4b4, Te6edf3messageTb4b4b4)

T8b949e# Check whether we need to make another announcement
Te6edf3announce_checkTb4b4b4(Tb4b4b4)

T8b949e#Sleep
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff10Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────